#pragma comment(linker,"/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int, int>
using namespace std;
const int N = 4e6 + 5;
const int M = 6e6 + 5;

namespace fastIO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
    bool IOerror = 0;

    inline char nc() {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if (p1 == pend) {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if (pend == p1) {
                IOerror = 1;
                return -1;
            }
        }
        return *p1++;
    }

    inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }

    inline bool read(int &x) {
        bool sign = 0;
        char ch = nc();
        x = 0;
        for (; blank(ch); ch = nc());
        if (IOerror)return false;
        if (ch == EOF) return false;
        if (ch == '-')sign = 1, ch = nc();
        for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0';
        if (sign)x = -x;
        return true;
    }

    struct Ostream_fwrite {
        char *buf, *p1, *pend;

        Ostream_fwrite() {
            buf = new char[BUF_SIZE];
            p1 = buf;
            pend = buf + BUF_SIZE;
        }

        void out(char ch) {
            if (p1 == pend) {
                fwrite(buf, 1, BUF_SIZE, stdout);
                p1 = buf;
            }
            *p1++ = ch;
        }

        void print(int x) {
            static char s[15], *s1;
            s1 = s;
            if (!x)*s1++ = '0';
            if (x < 0)out('-'), x = -x;
            while (x)*s1++ = x % 10 + '0', x /= 10;
            while (s1-- != s)out(*s1);
        }

        void print(char *s) { while (*s)out(*s++); }

        void println(char *s) {
            while (*s)out(*s++);
            out('\n');
        }

        void flush() {
            if (p1 != buf) {
                fwrite(buf, 1, p1 - buf, stdout);
                p1 = buf;
            }
        }

        ~Ostream_fwrite() { flush(); }
    } Ostream;

    inline void print(int x) { Ostream.print(x); }

    inline void print(char x) { Ostream.out(x); }

    inline void println(int x) {
        Ostream.print(x);
        Ostream.out('\n');
    }

    inline void printd(int x) {
        Ostream.print(x);
        Ostream.out(',');
    }

    inline void println(char x) {
        Ostream.out(x);
        Ostream.out('\n');
    }

    inline void print(char *s) { Ostream.print(s); }

    inline void println(char *s) { Ostream.println(s); }

#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;

int m, n, num;
int cur[15], val[M];
int ans[N][8], len[N];
pii p[N];

bool cmp(pii a, pii b) {
    return a.se > b.se;
}

struct G_Edge {
    struct Edge {
        int v, next;
    } edge[N];

    int head[N], cnt;

    void init(int n) {
        if(cnt != 0) n = cnt;
        cnt = 0;
        memset(head, -1, sizeof(int) * n);
    }

    void add(int u, int v) {
        edge[cnt] = {v, head[u]};
        head[u] = cnt++;
    }
}G1, G2, G3;

inline int get(int x) {
    return lower_bound(val + 1, val + n + 1, x) - val;
}

bool flag[N], in[N],  f[N];
int sta[N], dfn[N], low[N], bl[N], res, tail, k;
int is[N];

inline void add_ans(int now_len) {
    ans[num][1] = cur[1];
    ans[num][2] = cur[2];
    ans[num][3] = cur[3];
    if(now_len == 3) return ;
    ans[num][4] = cur[4];
    if(now_len == 4) return ;
    ans[num][5] = cur[5];
    if(now_len == 5) return ;
    ans[num][6] = cur[6];
    if(now_len == 6) return ;
    ans[num][7] = cur[7];
}

inline void pr(int d[], int now_len) {
    printd(val[d[1]]);
    printd(val[d[2]]);
    if(now_len == 3) {
        println(val[d[3]]); return ;
    }
    printd(val[d[3]]);
    if(now_len == 4) {
        println(val[d[4]]); return ;
    }
    printd(val[d[4]]);
    if(now_len == 5) {
        println(val[d[5]]); return ;
    }
    printd(val[d[5]]);
    if(now_len == 6) {
        println(val[d[6]]); return ;
    }
    printd(val[d[6]]);
    println(val[d[7]]);
}

void dfs(int u, int step, int rt) {
    if (u < rt || flag[u]) return;
    if(step > 4 && is[u] != rt) return ;
    cur[step] = u;
    if (step >= 3 && f[u]) {
        len[++num] = step;
        add_ans(step);
    }
    if(step >= 7) return ;
    flag[u] = true;
    for (int i = G1.head[u]; ~i; i = G1.edge[i].next) {
        dfs(G1.edge[i].v, step + 1, rt);
    }
    flag[u] = false;
}

void dfs1(int u, int step, int rt) {
    if(u < rt || flag[u]) return ;
    is[u] = rt;
    if(step >= 3) return ;
    flag[u] = true;
    for (int i = G3.head[u]; ~i; i = G3.edge[i].next) {
        dfs1(G3.edge[i].v, step + 1, rt);
    }
    flag[u] = false;
}

void tarjan(int u) {
    dfn[u] = low[u] = ++res;
    sta[++tail] = u;
    in[u] = true;
    int v;
    for (int i = G1.head[u]; ~i; i = G1.edge[i].next) {
        v = G1.edge[i].v;
        if (!dfn[v]) {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        } else if (in[v]) {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if (low[u] == dfn[u]) {
        ++k;
        do {
            v = sta[tail--];
            in[v] = false;
            bl[v] = k;
        } while (v != u);
    }
}
int main() {

//    freopen("/data/test_data.txt", "r", stdin);
//    freopen("/projects/student/output.txt", "w", stdout);
    freopen("./data/1406671/test_data.txt", "r", stdin);
    freopen("./z.out","w",stdout);
    int u, v, cost;
    while (read(u)) {
        read(v);
        read(cost);
        p[++m] = {u, v};
        val[++n] = u;
        val[++n] = v;
    }
    // 离散化
    G1.cnt = G2.cnt = G3.cnt = 0;
    sort(val + 1, val + n + 1);
    n = unique(val + 1, val + n + 1) - val - 1;
    sort(p + 1, p + m + 1, cmp);
    G1.init(n + 5);
    G2.init(n + 5);
    for (int i = 1; i <= m; i++) {
        p[i].fi = get(p[i].fi);
        p[i].se = get(p[i].se);
        G1.add(p[i].fi, p[i].se);
    }

    for (int i = 1; i <= n; i++) {
        if (!dfn[i]) {
            tarjan(i);
        }
    }
    G1.init(n + 5);
    G3.init(n + 5);
    for (int i = 1; i <= m; i++) {
        if (bl[p[i].fi] == bl[p[i].se]) {
            G1.add(p[i].fi, p[i].se);
            G3.add(p[i].se, p[i].fi);
            if(p[i].fi > p[i].se)
                G2.add(p[i].se, p[i].fi);
        }
    }
    bool ok = true;
    for (int i = 1; i <= n; i++) {
        cur[1] = i;
        ok = false;
        flag[i] = true;
        for(int j = G2.head[i]; ~j; j = G2.edge[j].next) {
            ok = true;
            f[G2.edge[j].v] = true;
            dfs1(G2.edge[j].v, 1, i);
        }
        flag[i] = false;

        if(ok)  {
            dfs(i, 1, i);
            for(int j = G2.head[i]; ~j; j = G2.edge[j].next) {
                f[G2.edge[j].v] = false;
            }
        }
    }

    println(num);

    for(int j = 3; j <= 7; j++)
        for(int i = 1; i <= num; i+=4) {
            if(len[i] == j) pr(ans[i], j);
            if(len[i+1] == j) pr(ans[i+1], j);
            if(len[i+2] == j) pr(ans[i+2], j);
            if(len[i+3] == j) pr(ans[i+3], j);
        }

    return 0;
}

